﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NHibernate;
using NHibernate.Criterion;
using Studentium.Entities;
using Studentium.Util;
using TopCoder.Util.Calendar.Entry;

namespace Studentium.UIElements
{    
    public partial class EditScheduleEntry : Form
    {
        private bool isNew;
        private CalendarEntry entry;
        private MainForm mainController;

        public EditScheduleEntry(CalendarEntry entry, MainForm mainController, bool isNew)
        {
            InitializeComponent();

            this.KeyPreview = true;
            this.KeyDown +=new KeyEventHandler(EditScheduleEntry_KeyDown);

            this.mainController = mainController;
            this.entry = entry;
            this.isNew = isNew;

            if (entry.Date <= DateTime.MinValue || entry.Date >= DateTime.MaxValue)
                entry.Date = DateTime.Now.AddMinutes(-DateTime.Now.Minute);

            datePicker.Value = entry.Date;
            classNameBox.DataSource = new[] { "BookClass1", "BookClass2", "Grammar", "Conversation", "Speaking", 
                                              "CaseStudy", "Prononciation", "Drama", "Movie", "Presentation" };
            classNameBox.Text = entry.Description;
            levelCombo.DataSource = Enum.GetValues(typeof(StudentLevel));
            levelCombo.SelectedItem = entry.Level;

            datePicker.Format = DateTimePickerFormat.Custom;
            datePicker.CustomFormat = "dd MMMM yyyy, HH:mm";

            if (!isNew)
                LoadClassAttendances();
        }

        private void LoadClassAttendances()
        {
            using (ISession session = mainController.GetSession())
            {
                IList<ClassAttendance> attendances = session.CreateCriteria(typeof (ClassAttendance)).
                    //Add(Expression.Eq("CalendarEntry.FullClassName", scheduleEntry.Description)).
                    //Add(Expression.Eq("CalendarEntry.Date", scheduleEntry.Date)).
                    Add(Expression.Eq("CalendarEntry", entry)).
                    List<ClassAttendance>();

                foreach (ClassAttendance classAttendance in attendances)
                {
                    if (classAttendance.Status == AttendenceStatus.Registered ||
                        classAttendance.Status == AttendenceStatus.Attended)
                    {
                        attendantsBox.Text += classAttendance.Student.FullName + Environment.NewLine;
                    }
                    if (classAttendance.Status == AttendenceStatus.WishList)
                    {
                        wishedToAttendBox.Text += classAttendance.Student.FullName + Environment.NewLine;
                    }
                }
            }
        }

        private void cancelBtn_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void removeBtn_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to delete schedule entry and all corresponding attendences?", "Question",
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                return;

            if (isNew)
            {                
                Close();
                return;
            }

            try
            {
                using (ISession session = mainController.GetSession())
                using (ITransaction transaction = session.BeginTransaction())
                {

                    IList<ClassAttendance> attendances = session.CreateCriteria(typeof(ClassAttendance)).
                        Add(Expression.Eq("CalendarEntry", entry)).
                        List<ClassAttendance>();

                    foreach (ClassAttendance classAttendance in attendances)
                    {
                        classAttendance.Student.Classes.Remove(classAttendance);
                        session.Delete(classAttendance);
                    }
                    // merge should be applied, because session may have object 
                    // with the same entry for some reason (possibly because of 'entry' in previous Criteria)
                    session.Delete(session.Merge(entry));
                    //session.Delete(entry);
                    transaction.Commit();
                }
            }
            catch (ObjectNotFoundException ex)
            {
                Log.log("Error during calendar entry removal", ex);
                MessageBox.Show("It seems entry was already deleted", "Warning", MessageBoxButtons.OK,
                                MessageBoxIcon.Warning);
                Close();
            }
            catch (Exception ex)
            {
                Log.log("Error during calendar entry removal", ex);
                MessageBox.Show("Cann't remove calendar entry", "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                Close();
            }


            mainController.ReloadCalendar(); 
            mainController.StudentsControl.ReloadStudentView();            

            Close();            
        }

        private void saveBtn_Click(object sender, EventArgs e)
        {
            entry.Date = datePicker.Value;

            if (classNameBox.Text.Trim().Length == 0)
            {
                MessageBox.Show("Class name cann't be empty", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            entry.Description = classNameBox.Text;
            entry.Level = (StudentLevel) levelCombo.SelectedItem;

            try
            {
                using (ISession session = mainController.GetSession())
                using (ITransaction transaction = session.BeginTransaction())
                {

                    // i don't know what merge is doing here - possibly in the past session already had entry
                    // right now i don't think it is necessary
                    session.SaveOrUpdate(session.Merge(entry));
                    transaction.Commit();
                }
            }
            catch (Exception ex)
            {
                Log.log("Error during calendar entry saving", ex);
                MessageBox.Show("Unfortunately calendar entry cann't be saved now", "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                Close();
            }

            Close();
            mainController.ReloadCalendar();
        }

        private void EditScheduleEntry_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                this.Close();
            }
        }
    }
}
